package uk.ac.lkl.lpp.model.xml;



import java.util.ArrayList;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import uk.ac.lkl.lpp.PedagogyPlan;
import uk.ac.lkl.lpp.model.PedagogyPlanModel;
import uk.ac.lkl.lpp.xml.ElementProcessor;
import uk.ac.lkl.lpp.xml.XMLException;


/**
 * 
 * <p>
 * Question: are we reinventing marshaling? need to check the state of the art.
 * a decent package should read an XML scheme and automatically generate the
 * processor classes.
 * </p>
 * 
 * <p>
 * To some extent, yes. I needed to get this done quickly since it was 'behind
 * the scenes'. I agree that you should look into packaged that help you do
 * this. I didn't have time.
 * </p>
 * 
 * <p>
 * Question: why is this class instanstiatable? Why not have a single instance
 * and a private constructor?
 * </p>
 * 
 * <p>
 * Answer: Yep. Should use the singleton pattern. Just part of the rushing.
 * </p>
 * 
 * @author Darren Pearce
 * @version $Revision: 604 $
 * @version $Date: 2008-02-15 13:52:19 +0000 (Fri, 15 Feb 2008) $
 * 
 */
public class XMLPedagogyPlanModelProcessor extends ElementProcessor {

    public static final String MODEL_VERSION_ATT = "version";


    private ArrayList<ModelElementProcessor> elementProcessors;


    public XMLPedagogyPlanModelProcessor() {
        super("PedagogyPlanModel");
        elementProcessors = new ArrayList<ModelElementProcessor>();
        createElementProcessors();
    }


    /**
     * Todo: have this in a configuration file in XML.
     * 
     * (XML to describe how the xml should be processed.)
     * 
     * Also: sets can be described generically in XML without need to specify
     * each type here and have separate classes for reading.
     * 
     */
    private void createElementProcessors() {
        // elementProcessors.add(new ListProcessor());
        elementProcessors.add(new ChunkPropertySetProcessor());
        elementProcessors.add(new ConceptSetProcessor());
        elementProcessors.add(new CognitiveActivitySetProcessor());
        elementProcessors.add(new TeachingMethodSetProcessor());
        elementProcessors.add(new SelectedTeachingMethodSetProcessor());
        elementProcessors.add(new TeachingMethodHoursAllocationSetProcessor());
        elementProcessors.add(new TeachingMethodGroupSizeSetProcessor());
        elementProcessors.add(new TopicSetProcessor());
        elementProcessors.add(new AssessmentMethodSetProcessor());
        elementProcessors.add(new ModuleAimSetProcessor());
        elementProcessors.add(new LearningOutcomeSetProcessor());
        elementProcessors.add(new AssociationSetProcessor());
        elementProcessors.add(new AllocationSetProcessor());
    }


    @Override
    public void convertDataToElements(PedagogyPlan plan,
                                      Document document,
                                      Element pedagogyPlanElement) {
        Element pedagogyPlanModelElement = document
                .createElement("PedagogyPlanModel");

        pedagogyPlanModelElement.setAttribute(MODEL_VERSION_ATT, String
                .valueOf(PedagogyPlanModel.LATEST_VERSION));

        for (ModelElementProcessor elementProcessor : elementProcessors)
            elementProcessor.convertDataToElements(
                                                   plan,
                                                   document,
                                                   pedagogyPlanModelElement);

        pedagogyPlanElement.appendChild(pedagogyPlanModelElement);
    }


    /**
     * The base class method convertElementsToData digs out the appropriate
     * elements from the DOM and then calls this method for each one.
     */
    public void convertElementToData(PedagogyPlan plan, Element element)
            throws XMLException {
        PedagogyPlanModel model = new PedagogyPlanModel();
        plan.setModel(model);

        // get data model version
        int version;
        String versionS = element.getAttribute(MODEL_VERSION_ATT);
        if (versionS == null || versionS.length() == 0) {
            version = 0;
        }
        else {
            version = Integer.parseInt(versionS);
        }
        model.setVersion(version);

        for (ModelElementProcessor elementProcessor : elementProcessors)
            elementProcessor.convertElementsToData(plan, element);
    }

}
